﻿using UnityEngine;
using System.Collections.Generic;
namespace Room
{
    public class RCMoveMonster : RCMoveBase
    {
        public RCMoveMonster(RoomCharactor owner)
            :base(owner)
        {
            type = MoveType.Monster;
        }

        #region agent
        NavMeshAgent _agent;
        NavMeshAgent agent
        {
            get
            {
                if (_agent == null)
                {
                    _agent = owner.gameObject.AddMissingComponent<NavMeshAgent>();
                    _agent.angularSpeed = 7200;
                    _agent.acceleration = 100;
                    _agent.radius = 0.0f;
                    _agent.speed = 5f;
                    _agent.autoRepath = false;
                }
                return _agent;
            }
        }
        #endregion

        private float rotateSpeed=180f, moveSpeed=4f;

        private Queue<Vector3> targets = new Queue<Vector3>();
        private bool needRotate;
        private bool running;

        public void Init(float rotateSpeed)
        {
            this.rotateSpeed = rotateSpeed;
        }

        public override void DoStart()
        {
            
        }

        public override void Tick()
        {
            if(targets.Count==0)
            {
                return;
            }
            Vector3 target = targets.Peek();


            if(needRotate)
            {
                float currentFaceTo = owner.transform.localEulerAngles.y;
                Vector3 delta = target - owner.transform.position;
                delta.y = 0;
                
                float targetFaceTo = Vector3.Angle(Vector3.forward, delta);
                if (delta.x < 0)
                    targetFaceTo = -targetFaceTo;

                currentFaceTo = Mathf.MoveTowardsAngle(currentFaceTo, targetFaceTo, rotateSpeed * Time.deltaTime);
                //currentFaceTo = targetFaceTo;
                owner.transform.localEulerAngles = new Vector3(0, currentFaceTo, 0);
                if(Mathf.Abs(GetNearAngle(currentFaceTo-targetFaceTo))< (rotateSpeed * Time.deltaTime)+1)
                {
                    owner.transform.LookAt(target);
                    MoveToTarget(target);
                    delta = target - owner.transform.position;
                    if(delta.magnitude<1f)
                    {
                        targets.Dequeue();
                    }
                }
            }
            else
            {
                owner.transform.LookAt(target);
                MoveToTarget(target);
                var delta = target - owner.transform.position;
                if (delta.magnitude < 1f)
                {
                    targets.Dequeue();
                }
            }
        }
        
        private void MoveToTarget(Vector3 target)
        {
            if(agent.isOnNavMesh)
            {
                float delta = Time.deltaTime * moveSpeed;
                float distance = (target - owner.transform.position).magnitude;
                delta = Mathf.Min(delta, distance);
                Vector3 newPosition = Vector3.MoveTowards(owner.transform.position, target, delta);
                Vector3 needMove = newPosition - owner.transform.position;
                agent.speed = moveSpeed;
                agent.Move(needMove);
            }
            
        }

        public override void MoveTo(Vector3 to)
        {
            targets.Clear();
            targets.Enqueue(to);
            owner.transform.LookAt(to);
        }

        public override void StopTo(Vector3 to)
        {
            targets.Clear();
            NavMeshPath path = new NavMeshPath();
            if(NavMesh.CalculatePath(owner.transform.position,to,NavMesh.AllAreas,path))
            {
                foreach(var it in path.corners)
                {
                    if (it == owner.transform.position)
                        continue;
                    targets.Enqueue(it);
                }
                needRotate = true;
            }
        }
        private float GetNearAngle(float ori)
        {
            float floor = Mathf.Floor(ori / 360);
            ori -= floor * 360f;
            if (ori > 180f)
                ori -= 360f;
            return ori;
        }
        public override void SetSpeed(float speed)
        {
            moveSpeed = speed;
        }
        public override bool IsMoving()
        {
            return targets.Count>0;
        }

        public override void ResetPosition()
        {
            NavMeshHit hit;
            if(NavMesh.SamplePosition(owner.transform.position,out hit,10,NavMesh.AllAreas))
            {
                owner.transform.position = hit.position;
            }
        }
    }

}

